import classnames from 'classnames';
import React, { useMemo } from 'react';
import styled from 'styled-components';

const WaveLayout = styled.div`
  &.wave {
    position: relative;
    width: 100%;
    height: 100%;
    border: var(--outer-border-width) solid var(--outer-border-color);
    padding: var(--outer-padding);
    border-radius: var(--border-radius);

    &.wave-triangle,
    &.wave-rhombus,
    &.wave-star {
      border: none;
      padding: 0;
      border-radius: 0;
    }

    &.wave-triangle {
      clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
    }
    &.wave-rhombus {
      clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
    }
    &.wave-star {
      clip-path: polygon(
        50% 0%,
        61% 35%,
        98% 35%,
        68% 57%,
        79% 91%,
        50% 70%,
        21% 91%,
        32% 57%,
        2% 35%,
        39% 35%
      );
    }
    .wave-inner {
      position: relative;
      z-index: 1;
      width: 100%;
      height: 100%;
      overflow: hidden;
      border-radius: var(--border-radius);
      background-color: var(--inner-background);
    }

    .wave-main {
      position: absolute;
      left: 0;
      bottom: -130%;
      width: 100%;
      height: 100%;
      background-color: var(--front-color);
      transform: translateY(calc(0% - var(--water-height)));
    }

    .waves {
      position: absolute;
      left: 0;
      bottom: 100%;
      width: 200%;
      stroke: none;
      /* 解决水球图中间有一条线问题 */
      box-shadow: 0 10px 4px 4px var(--front-color);

      &.waves-front {
        fill: var(--front-color);
        transform: translate(-50%, 0);
        animation: waves-front-move 5s linear infinite;
      }

      &.waves-back {
        display: var(--wave-display);
        fill: var(--back-color);
        transform: translate(0, 0);
        animation: waves-back-move 3s linear infinite;
      }
    }

    @keyframes waves-front-move {
      100% {
        transform: translate(0, 0);
      }
    }
    @keyframes waves-back-move {
      100% {
        transform: translate(-50%, 0);
      }
    }

    .wave-text {
      position: absolute;
      left: 0;
      top: 0;
      display: flex;
      align-items: center;
      justify-content: center;
      width: 100%;
      height: 100%;
    }
  }
`;

interface IConfigProps {
  /** 水球内部背景颜色 */ innerBackground?: React.CSSProperties['background'];
  /** 前面波纹颜色 */ frontColor?: React.CSSProperties['color'];
  /** 后面波纹颜色 */ backColor?: React.CSSProperties['color'];
  /** 外边框内边距 */ outerPadding?: React.CSSProperties['padding'];
  /** 外变宽宽度 */ outerBorderWidth?: React.CSSProperties['borderWidth'];
  /** 外边框颜色 */ outerBorderColor?: React.CSSProperties['borderColor'];
  /** 外围边框圆角程度 */ borderRadius?: React.CSSProperties['borderRadius'];
  /** 是否显示双波浪线 */ doubleWaves?: boolean;
  /** 波峰-波谷，值0-70，值越大，水面突出越明显 */ crests?: number;
}
const defaultConfig: IConfigProps = {
  /** 水球内部背景颜色 */ innerBackground: 'transparent',
  /** 前面波纹颜色 */ frontColor: '#0bc8e8',
  /** 后面波纹颜色 */ backColor: '#0b6d98',
  /** 外边框内边距 */ outerPadding: '4px',
  /** 外变宽宽度 */ outerBorderWidth: '4px',
  /** 外边框颜色 */ outerBorderColor: '#0bc8e8',
  /** 外围边框圆角程度 */ borderRadius: '50%',
  /** 是否显示双波浪线 */ doubleWaves: true,
  /** 波峰-波谷，值0-70，值越大，水面突出越明显 */ crests: 40,
};

interface Props {
  rate?: string;
  config?: object;
  /** 默认：圆形 */
  shape?: 'default' | 'circle' | 'triangle' | 'rhombus' | 'star';
  text?: React.ReactNode;
  children?: React.ReactNode;
  style?: React.CSSProperties;
}

export const Wave: React.FC<Props> = (props) => {
  const { rate = '0', config, shape, text, children, style } = props;

  const path = useMemo(() => {
    let obj = Object.assign({}, defaultConfig, config);
    let crests = obj.crests ?? 0;

    if (crests <= 0) {
      crests = 0;
    } else if (crests >= 70) {
      crests = 70;
    }

    return `M 0 70 Q 75 ${
      70 - crests
    },150 70 T 300 70 T 450 70 T 600 70 L 600 140 L 0 140 L 0 70Z`;
  }, [config]);

  const styleObj = useMemo(() => {
    let obj = Object.assign({}, defaultConfig, config);
    let rateVal = Number.parseFloat(rate?.replace('%', ''));
    let waveDisplay = obj.doubleWaves ? 'block' : 'none';

    if (rateVal <= 0) {
      rateVal = 0;
    } else if (rateVal >= 100) {
      rateVal = 100;
    }

    return {
      '--inner-background': obj.innerBackground,
      '--front-color': obj.frontColor,
      '--back-color': obj.backColor,
      '--outer-padding': obj.outerPadding,
      '--outer-border-width': obj.outerBorderWidth,
      '--outer-border-color': obj.outerBorderColor,
      '--border-radius': obj.borderRadius,
      '--water-height': `${rateVal}%`,
      '--wave-display': waveDisplay,
    };
  }, [path, config]);

  return (
    <WaveLayout
      className={classnames('wave', { [`wave-${shape}`]: shape })}
      style={{ ...style, ...(styleObj as React.CSSProperties) }}>
      <div className="wave-inner">
        <div className="wave-main">
          <svg
            xmlns="http://www.w3.org/2000/svg"
            version="1.0"
            className="waves waves-back"
            viewBox="0 0 600 140">
            <path d={path} />
          </svg>
          <svg
            xmlns="http://www.w3.org/2000/svg"
            version="1.0"
            className="waves waves-front"
            viewBox="0 0 600 140">
            <path d={path} />
          </svg>
        </div>
        {(text || children) && (
          <div className="wave-text">{text || children}</div>
        )}
      </div>
    </WaveLayout>
  );
};
